package io.kiki.sba.registry.server.clientInterface.resource;

import com.google.common.base.Joiner;
import io.kiki.sba.registry.api.exchange.DataExchanger;
import io.kiki.sba.registry.common.model.metaserver.nodes.ClientInterfaceNode;
import io.kiki.sba.registry.common.model.slot.Slot;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import io.kiki.sba.registry.server.clientInterface.slot.SlotsCache;
import io.kiki.sba.registry.server.shared.meta.MetaServerService;
import io.kiki.sba.registry.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


@Path("api/servers")
public class SessionOpenResource {

    @Autowired
    private Config config;

    @Autowired
    private MetaServerService metaNodeService;

    @Autowired
    private SlotsCache slotsCache;

    @Autowired
    private DataExchanger boltDataExchanger;

    @GET
    @Path("query.json")
    @Produces(MediaType.APPLICATION_JSON)
    public List<String> getSessionServerListJson(@QueryParam("zone") String zone) {
        if (StringUtils.isBlank(zone)) {
            zone = config.getSessionServerRegion();
        }

        if (StringUtils.isNotBlank(zone)) {
            zone = zone.toUpperCase();
        }
        return getSessionServers(zone);
    }

    @GET
    @Path("query")
    @Produces(MediaType.TEXT_PLAIN)
    public String getSessionServerList(@QueryParam("zone") String zone) {
        return Joiner.on(";").join(getSessionServerListJson(zone));
    }

    @GET
    @Path("queryWithWeight")
    @Produces(MediaType.TEXT_PLAIN)
    public String getSessionServerListWithConnNum(@QueryParam("zone") String zone) {
        if (StringUtils.isBlank(zone)) {
            zone = config.getSessionServerRegion();
        }

        if (StringUtils.isNotBlank(zone)) {
            zone = zone.toUpperCase();
        }
        return Joiner.on(";").join(getSessionServersWithConnNum(zone));
    }

    @GET
    @Path("connectionNum")
    @Produces(MediaType.TEXT_PLAIN)
    public int getCurrentSessionConnNum() {
        return boltDataExchanger.getServer(config.getServerPort()).getChannelList().size();
    }

    @GET
    @Path("alive")
    public String checkAlive() {
        return "OK";
    }

    /**
     * Get server list for current data center
     */
    @GET
    @Path("dataCenter")
    @Produces(MediaType.APPLICATION_JSON)
    public List<String> getCurrentDataCenterServerList() {
        return getSessionServers(null);
    }

    private List<String> getSessionServers(String zone) {
        List<String> serverList = metaNodeService.getSessionServerList(zone);

        serverList = serverList.stream().map(server -> server + ":" + config.getServerPort()).collect(Collectors.toList());
        return serverList;
    }

    private List<String> getSessionServersWithConnNum(String zone) {
        List<ClientInterfaceNode> serverList = metaNodeService.getSessionNodeWithConnNumList(zone);
        List<String> serverWithConnNumList = new ArrayList<>();
        serverList.forEach(item -> {
            serverWithConnNumList.add(item.getUrl().getIp() + ":" + config.getServerPort() + "?weight=" + item.getWeight());
        });
        return serverWithConnNumList;
    }

    @GET
    @Path("slot")
    @Produces(MediaType.APPLICATION_JSON)
    public Slot getSlot(@QueryParam("dataInfoId") String dataInfoId) {
        StringUtil.checkNotBlank(dataInfoId, "dataInfoId");
        return slotsCache.getSlot(config.getDataCenter(), dataInfoId);
    }
}
